package com.maduar.demo.jvm;

import io.swagger.models.auth.In;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Description: 查看数字的原码，反码，补码
 *
 * @author maduar maduar@163.com
 * @date 2021-03-12 14:34
 */
public class NumberCode {

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param number 整数数字
     * @return 二进制
     * @Author: danny.pang
     * @Date: 2021-03-12 14:34:49
     */
    public static String getBinaryString(int number) {
        StringBuilder result = new StringBuilder();
        int execNumber = number;
        boolean negativeBool = false;

        // 如果是负数，取绝对值
        if (execNumber < 0) {
            execNumber = Math.abs(execNumber);
            negativeBool = true;
        }

        for (int i = 0; i < 32; i++) {
            int t = (execNumber & 0x80000000 >>> i) >>> (31 - i);
            result.append(t);
        }

        // 如果是负数，将第一位符号位变为1
        if (negativeBool) {
            result.replace(0, 1,"1");
        }

        return result.toString();
    }

    /**
     * 1. 接口名称: 取反码
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 15:26:35
     */
    public static String getBinaryAntiCode(int number) {
        // 取得二进制
        String binaryString = getBinaryString(number);
        int length = binaryString.length();
        StringBuilder result = new StringBuilder();

        result.append(binaryString.substring(0, 1));
        for (int i = 1; i < length; i++) {
            int key = Integer.parseInt(binaryString.substring(i, i + 1));
            result.append(1 - key);
        }

        return result.toString();
    }

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 15:39:30
     */
    public static String getComplement(int number) {
        // 取得二进制
        String binaryString = getBinaryString(number);
        // 正数的补码就是其本身
        if (number >= 0) {
            return binaryString;
        }

        // 负数的补码是反码加1
        int length = binaryString.length();
        StringBuilder result = new StringBuilder();

        return null;
    }

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 15:53:09
     */
    public static int getOneInBinary(int number) {
        int res = 0;
        while (number > 0) {
            res += 1;
            number &= number - 1;
        }
        return res;
    }

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 15:53:09
     */
    public static int getOneInBinary2(int number) {
        int res = 0;
        while (number > 0) {
            res += number & 1;
            number >>= 1;
        }
        return res;
    }

    /**
     * 1. 接口名称: 求二进制中1的间距
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 16:32:51
     */
    public static int getWidth(int n) {
        int last = 0;
        int current = 0;
        int i = 1;
        int sign = 0;

        while (n != 0) {
            sign = n & 1;
            // 最后一位是1
            if (sign == 1) {
                // 说明不是第一次出现1
                if (last > 0) {
                    current = Math.max(current, i - last);
                }
                last = i;
            }
            n >>>= 1;
            i++;

        }

        return current;
    }

    /**
     * 1. 接口名称: suma
     * 2. 接口文档编号:
     * 3. 接口详细说明: a. 思路，执照10进制加法，把按位加
     *                b. 最后反转字符串，因为是从右侧开始存储的相加后的结果
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 17:23:40
     */
    public static String addBinary(String a, String b) {
        int aLength = a.length();
        int bLength = b.length();
        int length = Math.max(aLength, bLength);
        int carry = 0;

        StringBuilder result = new StringBuilder();


        for (int i = 0; i < length; i++) {
            carry += i < aLength
                    ? a.charAt(aLength - 1 - i) - '0'
                    : 0;

            carry += i < bLength
                    ? b.charAt(bLength - 1 - i) - '0'
                    : 0;
            result.append((char) (carry % 2 + '0'));
            carry /= 2;
        }

        if (carry > 0) {
            result.append('1');
        }

        return result.reverse().toString();
    }

    /**
     * 1. 接口名称: 反转二进制
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 22:43:29
     */
    public static int reverseBinary(int n) {
        int res = 0;
        for (int i = 0; i < 32; i++) {
            res <<= 1;
            res += n & 1;
            n >>= 1;
        }

        return res;
    }

    /**
     * 1. 接口名称: 交替位二进制
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 23:09:53
     */
    public static boolean hasAlternatingBits(int n) {
        int code = n;
        int last = -1;

        while (code != 0) {
            int current = code & 1;
            if (current == last) {
                return false;
            }

            last = current;
            code >>= 1;
        }
        return true;
    }

    /**
     * 1. 接口名称: 判断有没有连续的1出现
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-12 23:35:02
     */
    public static boolean checkOnesSegment(String s) {
        int length = s.length();
        char signChar = 1;
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            if (c == '1' && signChar == '0') {
                return false;
            } else {
                signChar = c;
            }
        }

        return true;
    }

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-13 00:05:42
     */
    public static int countBinarySubstrings(String s) {
        int length = s.length();
        List<Integer> list = new ArrayList<>();
        char c = '0';
        int count = 1;
        int sum = 0;

        for (int i = 0; i < length; i++) {
            char current = s.charAt(i);
            if (i == 0) {
                c = current;
                continue;
            }

            if (current == c) {
                count++;
            } else {
                list.add(count);
                count = 1;
            }

            c = current;
        }

        list.add(count);

        int size = list.size();
        if (size > 0) {
            for (int i = 0; i < size - 1; i++) {
                sum += Math.min(list.get(i), list.get(i + 1));
            }
        }

        return sum;
    }

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-13 00:05:42
     */
    public static int countBinarySubstrings2(String s) {
        int ptr = 0;
        int length = s.length();
        int last = 0;
        int ans = 0;
        while (ptr < length) {
            char c = s.charAt(ptr);
            int count = 0;
            while (ptr < length && s.charAt(ptr) == c) {
                ++ptr;
                ++count;
            }

            ans += Math.min(count, last);
            last = count;
        }

        return ans;
    }

    /**
     * 1. 接口名称:
     * 2. 接口文档编号:
     * 3. 接口详细说明:
     *
     * @param
     * @return
     * @Author: danny.pang
     * @Date: 2021-03-13 01:01:40
     */
    public static List<Boolean> prefixesDivBy5(int[] A) {
        int length = A.length;
        List<Boolean> list = new ArrayList<>();
        int prefix = 0;

        for (int i = 0; i < length; i++) {
            prefix = ((prefix << 1) + A[i]) % 5;
            list.add(prefix == 0);
        }
        return list;
    }
}
